package com.css.fxfzypg.modules.earthquakedisasterloss.service.impl;

import com.css.fxfzypg.base.response.RestResponse;
import com.css.fxfzypg.modules.SettingSeismic.entity.SeismicIntensityRelation;
import com.css.fxfzypg.modules.SettingSeismic.repository.IntensityRelationRepository;
import com.css.fxfzypg.modules.baseData.entity.PbeEntity;
import com.css.fxfzypg.modules.baseData.service.EmergencyShelterService;
import com.css.fxfzypg.modules.baseData.service.PbeService;
import com.css.fxfzypg.modules.earthquakedisasterloss.repository.SettingSeismicInfluencefliedRepository;
import com.css.fxfzypg.modules.earthquakedisasterloss.service.CountMaterialService;
import com.css.fxfzypg.modules.earthquakedisasterloss.vo.SeismicInfluencefliedVO;
import com.css.fxfzypg.modules.model.entity.Material;
import com.css.fxfzypg.modules.model.service.MaterialService;
import com.css.fxfzypg.modules.resultupload.repository.entity.ResultDetailsEntity;
import com.css.fxfzypg.modules.resultupload.repository.entity.ResultMainEntity;
import com.css.fxfzypg.modules.resultupload.service.ResultService;
import com.css.fxfzypg.modules.resultupload.service.ResultTotalService;
import com.css.fxfzypg.util.PlatformDateUtils;
import com.css.fxfzypg.util.PlatformObjectUtils;
import com.css.fxfzypg.util.PlatformSessionUtils;
import com.css.fxfzypg.util.ResponseCreator;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: fxfzypg
 * @Author: lhl
 * @CreateDate: 2022/10/12 13:59
 */
@Service
public class CountMaterialServiceImpl implements CountMaterialService {

    @Resource
    MaterialService materialService;
    @Resource
    private SettingSeismicInfluencefliedRepository settingSeismicInfluencefliedRepository;
    @Resource
    ResultTotalService resultTotalService;
    @Resource
    EmergencyShelterService emergencyShelterService;
    @Resource
    IntensityRelationRepository intensityRelationRepository;
    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResponse countMaterial(String taskId, String modelId) {
        RestResponse restResponse = null;
        try {
            if (PlatformObjectUtils.isNotEmpty(redisTemplate.opsForValue().get(taskId))) {
                return RestResponse.fail(503, "该任务的正在被其他人计算，请稍后再操作！！！");
            }
            redisTemplate.opsForValue().set(taskId, "7-1");
            List<SeismicInfluencefliedVO> voList = settingSeismicInfluencefliedRepository.find3ByTaskId(taskId);
            if (voList.size() < 1) {
                return RestResponse.fail(503, "请生成该任务下的地震影响场！");
            }
            Map<String, BigDecimal[]> detailsMap = new HashMap<>();
            BigDecimal[] details = null;

            ResultDetailsEntity d = null;
            //物资需求评估模型的id
            Material modelById = materialService.getModelById(modelId);
            for (SeismicInfluencefliedVO s : voList) {
                String key1 = taskId + "-" + s.getFaultNum() + "-" + s.getEarthquakeLevel() +
                        "-" + s.getAngle() + "-" + "2";
                if (d == null) {
                    d = resultTotalService.getResultDetailsEntity(taskId, s.getFaultNum(), s.getEarthquakeLevel(), s.getAngle());
                } else {
                    if (!key1.equals(taskId + "-" + d.getSort() + "-" + d.getMagnitude() +
                            "-" + d.getAngle() + "-" + "2")) {
                        d = resultTotalService.getResultDetailsEntity(taskId, s.getFaultNum(), s.getEarthquakeLevel(), s.getAngle());
                    }
                }
                if (PlatformObjectUtils.isEmpty(d)) {
                    continue;
                }
                if (PlatformObjectUtils.isEmpty(d.getResettledNum())) {
                    return RestResponse.fail(503, "请先计算该任务下的需紧急安置人员！");
                }
                BigDecimal sumAnZhi = new BigDecimal(d.getResettledNum());//需安置人员计算模型-总待安置人数

                if (PlatformObjectUtils.isEmpty(d.getInjuredNum())) {
                    return RestResponse.fail(503, "请先计算该任务下的人员伤亡！");
                }
                BigDecimal shoushan = new BigDecimal(d.getInjuredNum());//人员伤亡计算模型-受伤人数

                if (PlatformObjectUtils.isEmpty(d.getResettledNum())) {
                    return RestResponse.fail(503, "请生成该任务下的地震影响场！");
                }
                BigDecimal R = new BigDecimal(d.getDisasterNum());//受灾人数（万人）
                R = R.multiply(BigDecimal.valueOf(10000));//(人)

                List<Integer> esMaxpeopleByInfluenceflyId = emergencyShelterService.getEsMaxpeopleByInfluenceflyId(s.getInfluencefliedId());
                int sumRongNa1 = 0;//基础数据应急避难场所-灾区范围内应急避难场所可容纳人数
                for (Integer sumRongNa : esMaxpeopleByInfluenceflyId) {
                    sumRongNa1 = sumRongNa1 + sumRongNa;
                }

                //帐篷计算系数
                BigDecimal ratio1 = modelById.getRatio1();
                //季节系数
                BigDecimal ratio2 = modelById.getRatio2();

                BigDecimal ratio6 = modelById.getRatio6();//一付担架平均可以运送14个伤员
                BigDecimal ratio7 = modelById.getRatio7();//每5个需安置人员一床棉被
                BigDecimal ratio8 = modelById.getRatio8();//每需安置人员人20公斤
                BigDecimal ratio9 = modelById.getRatio9();//每人每天二公斤
                BigDecimal ratio10 = modelById.getRatio10();//连续供应十天
                BigDecimal ratio11 = modelById.getRatio11();//为受灾人口的1/250
                BigDecimal ratio12 = modelById.getRatio12();//是临时厕所的1/3
                //救援物资需求包括帐篷需求、担架需求、棉被需求、食品需求、饮水需求、临时厕所需求、临时浴室需求。
                // 1）帐篷(顶)=帐篷计算系数 ×（总待安置人数-灾区范围内应急避难场所可容纳人数）× 季节系数
                // 帐篷计算系数为0.1，季节系数：春季（1）、夏季（0.8）、秋季（1）、冬季（1.2），应急避难场所可容纳人数使用基础数据应急避难场所空间数据计算。
                // 2）担架需求：地震中伤员运送最好的工具之一是担架，一付担架平均可以运送14个伤员。
                // 3）棉被需求：救灾棉被按照每5个需安置人员一床棉被来供应。
                // 4）食品需求：救灾食品按照每需安置人员人20公斤来准备。
                // 5）饮水需求：应急期清洁饮水按照受灾人口每人每天二公斤计算，连续供应十天。
                // 6）临时厕所需求：临时厕所数目为受灾人口的1/250。
                // 7）临时浴室需求：临时浴室是临时厕所的1/3。

                //帐篷(顶)
                BigDecimal zhangpeng = BigDecimal.ZERO;
                if (sumAnZhi.compareTo(BigDecimal.valueOf(sumRongNa1)) > 0) {
                    zhangpeng = ratio1.multiply(sumAnZhi.subtract(BigDecimal.valueOf(sumRongNa1))).multiply(ratio2).setScale(0, RoundingMode.DOWN);
                }
                //担架
                BigDecimal danjia = shoushan.divide(ratio6, 0, RoundingMode.DOWN);
                //棉被
                BigDecimal mianbei = sumAnZhi.divide(ratio7, 0, RoundingMode.DOWN);
                //食品
                BigDecimal food = sumAnZhi.multiply(ratio8).divide(BigDecimal.valueOf(1000), 0, RoundingMode.DOWN);
                //饮水
                BigDecimal yinshui = R.multiply(ratio9).multiply(ratio10).divide(BigDecimal.valueOf(1000), 0, RoundingMode.DOWN);
                //临时厕所
                BigDecimal cesuo = ratio11.multiply(R).setScale(0, RoundingMode.DOWN);
                //临时浴室
                BigDecimal yushi = cesuo.multiply(ratio12).setScale(0, RoundingMode.DOWN);

                BigDecimal ratio13 = modelById.getRatio13();//每位伤员需要0.6平方米
                BigDecimal ratio14 = modelById.getRatio14();//每五位伤员需要一张病床
                BigDecimal ratio15 = modelById.getRatio15();//平均每位伤员50毫升
                //资料资源需求包括病房需求、病床需求、手术用血浆需求。
                // 1）病房需求，按照每位伤员需要0.6平方米计算。
                // 2）病床需求，按每五位伤员需要一张病床计算。
                // 3）手术用血浆，按平均每位伤员50毫升计算。
                //病房
                BigDecimal bingfang = shoushan.multiply(ratio13).setScale(0, RoundingMode.DOWN);
                //病床
                BigDecimal bingchuang = shoushan.divide(ratio14, 0, RoundingMode.DOWN);
                //手术用血浆
                BigDecimal xuejiang = shoushan.multiply(ratio15).divide(BigDecimal.valueOf(1000), 0, RoundingMode.DOWN);

                if (detailsMap.containsKey(key1)) {
                    details = detailsMap.get(key1);
                    details[0] = details[0].add(zhangpeng);
                    details[1] = details[1].add(danjia);
                    details[2] = details[2].add(mianbei);
                    details[3] = details[3].add(food);
                    details[4] = details[4].add(yinshui);
                    details[5] = details[5].add(cesuo);
                    details[6] = details[6].add(yushi);
                    details[7] = details[7].add(bingfang);
                    details[8] = details[8].add(bingchuang);
                    details[9] = details[9].add(xuejiang);
                } else {
                    details = new BigDecimal[10];
                    details[0] = zhangpeng;
                    details[1] = danjia;
                    details[2] = mianbei;
                    details[3] = food;
                    details[4] = yinshui;
                    details[5] = cesuo;
                    details[6] = yushi;
                    details[7] = bingfang;
                    details[8] = bingchuang;
                    details[9] = xuejiang;
                }
                detailsMap.put(key1, details);
            }

            Map<String, ResultMainEntity> listMap = new HashMap<>();
            ResultMainEntity r = null;
            for (Map.Entry<String, BigDecimal[]> entry : detailsMap.entrySet()) {
                ResultDetailsEntity entity = new ResultDetailsEntity();
                String[] split = entry.getKey().split("-");
                entity.setTaskId(split[0]);
                entity.setSort(split[1]);
                entity.setMagnitude(new BigDecimal(split[2]));
                entity.setAngle(split[3]);

                BigDecimal[] value = entry.getValue();
                entity.setTentNum(String.valueOf(value[0].intValue()));
                entity.setStretcherNum(String.valueOf(value[1].intValue()));
                entity.setQuiltsNum(String.valueOf(value[2].intValue()));
                entity.setFoodsNum(String.valueOf(value[3].intValue()));
                entity.setWaterNum(String.valueOf(value[4].intValue()));
                entity.setBathroomNum(String.valueOf(value[5].intValue()));
                entity.setShowersNum(String.valueOf(value[6].intValue()));
                entity.setSickroomNum(String.valueOf(value[7].intValue()));
                entity.setSickbedNum(String.valueOf(value[8].intValue()));
                entity.setPlasmaNum(String.valueOf(value[9].intValue()));

                entity.setUpdateId(PlatformSessionUtils.getUserId());
                entity.setUpdateTime(PlatformDateUtils.getCurrentTimestamp());
                entity.setDataSource("2");
                resultTotalService.updateResultDetailsEntity(entity);

                String key = taskId + "-" + entity.getSort() + "-" + entity.getMagnitude() + "-" + "2";
                if (listMap.containsKey(key)) {
                    r = listMap.get(key);
                    r.setTentNumBefore(compareTo(value[0], r.getTentNumBefore()));
                    r.setStretcherNumBefore(compareTo(value[1], r.getStretcherNumBefore()));
                    r.setQuiltsNumBefore(compareTo(value[2], r.getQuiltsNumBefore()));
                    r.setFoodsNumBefore(compareTo(value[3], r.getFoodsNumBefore()));
                    r.setWaterNumBefore(compareTo(value[4], r.getWaterNumBefore()));
                    r.setBathroomNumBefore(compareTo(value[5], r.getBathroomNumBefore()));
                    r.setShowersNumBefore(compareTo(value[6], r.getShowersNumBefore()));
                    r.setSickroomNumBefore(compareTo(value[7], r.getSickroomNumBefore()));
                    r.setSickbedNumBefore(compareTo(value[8], r.getSickbedNumBefore()));
                    r.setPlasmaNumBefore(compareTo(value[9], r.getPlasmaNumBefore()));
                } else {
                    r = new ResultMainEntity();
                    r.setTentNumBefore(value[0].intValue() + "-0");
                    r.setStretcherNumBefore(value[1].intValue() + "-0");
                    r.setQuiltsNumBefore(value[2].intValue() + "-0");
                    r.setFoodsNumBefore(value[3].intValue() + "-0");
                    r.setWaterNumBefore(value[4].intValue() + "-0");
                    r.setBathroomNumBefore(value[5].intValue() + "-0");
                    r.setShowersNumBefore(value[6].intValue() + "-0");
                    r.setSickroomNumBefore(value[7].intValue() + "-0");
                    r.setSickbedNumBefore(value[8].intValue() + "-0");
                    r.setPlasmaNumBefore(value[9].intValue() + "-0");
                }
                listMap.put(key, r);
            }
            resultTotalService.updateResultMainEntity(listMap, "3");

            SeismicIntensityRelation byTaskId = intensityRelationRepository.getByTaskId(taskId);
            byTaskId.setModel6Id(modelId);
            byTaskId.setExtends2("1");
            byTaskId.setButton6_status1("1");
            intensityRelationRepository.updateSeismicIntensityRelation(byTaskId);

            return ResponseCreator.createSuccessResponse("计算成功!");
        } catch (Exception e) {
            e.printStackTrace();
            restResponse = RestResponse.fail("计算失败!");
            return restResponse;
        } finally {
            redisTemplate.delete(taskId);
            if (restResponse != null) {
                if (restResponse.getCode() != 200) {
                    //事务手动回滚
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                }
            }
        }
    }

    private String compareTo(BigDecimal num1, String num2) {
        // num1:5 8 4 3
        // num2:10-0
        String[] split = num2.split("-");//5 10
        for (int i = 0; i < split.length; i++) {
            if (i == 0 && num1.compareTo(new BigDecimal(split[0])) < 0) {
                if (split.length == 2) {
                    if (new BigDecimal(split[0]).compareTo(new BigDecimal(split[1])) > 0) {
                        split[1] = String.valueOf(new BigDecimal(split[0]).intValue());
                        split[0] = String.valueOf(num1.intValue());
                    } else {
                        split[0] = String.valueOf(num1.intValue());
                        split[1] = String.valueOf(new BigDecimal(split[1]).intValue());
                    }
                } else {
                    split[0] = String.valueOf(num1.intValue());
                    split[1] = String.valueOf(new BigDecimal(split[1]).intValue());
                }
            } else if (i == 1 && num1.compareTo(new BigDecimal(split[1])) > 0) {
                split[0] = String.valueOf(new BigDecimal(split[0]).intValue());
                split[1] = String.valueOf(num1.intValue());
            }
        }
        num2 = split[0] + "-" + split[1];
        return num2;
    }
}
